package com.ruoyi.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.WebConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.dto.ArticleDto;
import com.ruoyi.system.mapper.SysLabelsMapper;
import com.ruoyi.system.service.ISolrService;
import javafx.scene.media.EqualizerBand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.SysArticleMapper;
import com.ruoyi.system.domain.SysArticle;
import com.ruoyi.system.service.ISysArticleService;

/**
 * 文章Service业务层处理
 *
 * @author king
 * @date 2022-07-15
 */
@Slf4j
@Service
public class SysArticleServiceImpl extends ServiceImpl<SysArticleMapper, SysArticle> implements ISysArticleService {
    @Autowired
    private SysArticleMapper sysArticleMapper;

    @Autowired
    private SysLabelsMapper labelsMapper;

    @Autowired
    private ISolrService solrService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 获取文章详情
     *
     * @param articleId
     * @return
     */
    @Override
    public AjaxResult getArticleDetailById(Integer articleId) {
        //先从redis中获取详情
        SysArticle cacheObject = redisCache.getCacheObject(CacheConstants.SYS_ARTICLE_KEY + articleId);
        //缓存中存在
        if (ObjectUtil.isNotNull(cacheObject)) {
            //增加阅读量
            Long viewCount = redisCache.getCacheObject(CacheConstants.KEY_ARTICLE_VIEW_COUNT + articleId);
            redisCache.setCacheObject(CacheConstants.KEY_ARTICLE_VIEW_COUNT+articleId,viewCount+1l);
            sysArticleMapper.update(null, new LambdaUpdateWrapper<SysArticle>().setSql(true, "view_count=" + viewCount)
                    .eq(SysArticle::getId, articleId));
            log.info("article:" + articleId + "view_count更新成功");
            return AjaxResult.success(cacheObject);
        }
        //从数据库中查询
        SysArticle article4Db = sysArticleMapper.selectById(articleId);
        //查询上一篇 下一篇文章
        SysArticle lastArticle = sysArticleMapper.selectOne(new LambdaQueryWrapper<SysArticle>()
                .select(SysArticle::getId, SysArticle::getTitle, SysArticle::getCover, SysArticle::getSummary)
                .ne(SysArticle::getState, WebConstants.article.ARTICLE__DELETE_STATE)
                .lt(SysArticle::getId, article4Db.getId())
                .orderByDesc(SysArticle::getId)
                .last("limit 1"));
        SysArticle nextArticle = sysArticleMapper.selectOne(new LambdaQueryWrapper<SysArticle>()
                .select(SysArticle::getId, SysArticle::getTitle, SysArticle::getCover, SysArticle::getSummary)
                .ne(SysArticle::getState, WebConstants.article.ARTICLE__DELETE_STATE)
                .gt(SysArticle::getId, article4Db.getId())
                .orderByAsc(SysArticle::getId)
                .last("limit 1"));
        article4Db.setLastArticle(ObjectUtil.isNotNull(lastArticle) ? BeanCopyUtils.copyObject(lastArticle, ArticleDto.class) : null);
        article4Db.setNextArticle(ObjectUtil.isNotNull(nextArticle) ? BeanCopyUtils.copyObject(nextArticle, ArticleDto.class) : null);
        //设置阅读量的key
        Long view = redisCache.getCacheObject(CacheConstants.KEY_ARTICLE_VIEW_COUNT + articleId);
        if (ObjectUtil.isNull(view)) {
            Long newView = article4Db.getViewCount() + 1;
            redisCache.setCacheObject(CacheConstants.KEY_ARTICLE_VIEW_COUNT + articleId, newView);
        } else {
            //缓存中存在更新到mysql
            redisCache.incr(CacheConstants.KEY_ARTICLE_VIEW_COUNT + articleId);
            article4Db.setViewCount(view + 1L);
            sysArticleMapper.updateById(article4Db);
            //更新搜索引擎中的数据
            solrService.updateArticle(article4Db);
        }
        //文件格式转化
        //放入缓存中
        redisCache.setCacheObject(CacheConstants.SYS_ARTICLE_KEY + articleId, article4Db, 15, TimeUnit.MINUTES);
        return AjaxResult.success(article4Db);
    }

    /**
     * 发布文章
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public AjaxResult getPublishArticle(Integer pageNo, Integer pageSize, String caetgoryId, String label) {
        LambdaQueryWrapper<SysArticle> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(SysArticle.class, info -> !info.getColumn().equals("content"))
                .eq(StrUtil.isNotEmpty(caetgoryId), SysArticle::getCategoryId, caetgoryId)
                .eq(SysArticle::getState, WebConstants.article.ARTICLE_PUBLISH_STATE)
                .like(StrUtil.isNotEmpty(label), SysArticle::getLabels, label)
                .orderByDesc(SysArticle::getCreateTime, SysArticle::getId);
        Page<SysArticle> page = new Page<>(pageNo, pageSize);
        Page<SysArticle> articlePage = sysArticleMapper.selectPage(page, queryWrapper);
        return AjaxResult.success(articlePage);
    }

    /**
     * 置顶文章
     *
     * @return
     */
    @Override
    public AjaxResult getTopArticle() {
        SysArticle article = new SysArticle();
        article.setState(WebConstants.article.ARTICLE_TOP_STATE);
        List<SysArticle> topArticleList = sysArticleMapper.selectTopArticle(article);
        return AjaxResult.success(topArticleList);
    }

    /**
     * 查询文章
     *
     * @param id 文章主键
     * @return 文章
     */
    @Override
    public SysArticle selectSysArticleById(Long id) {
        return sysArticleMapper.selectSysArticleById(id);
    }

    /**
     * 查询文章列表
     *
     * @param sysArticle 文章
     * @return 文章
     */
    @Override
    public List<SysArticle> selectSysArticleList(SysArticle sysArticle) {
        return sysArticleMapper.selectSysArticleList(sysArticle);
    }

    /**
     * 新增文章
     *
     * @param sysArticle 文章
     * @return 结果
     */
    @Override
    public AjaxResult insertSysArticle(SysArticle sysArticle) {
        //检查数据
        if (StringUtils.isEmpty(sysArticle.getTitle())) {
            return AjaxResult.error("标题不可以为空");
        }
        if (StringUtils.isEmpty(sysArticle.getContent())) {
            return AjaxResult.error("内容不可为空");
        }
        if (StringUtils.isEmpty(sysArticle.getCover())) {
            return AjaxResult.error("封面不可为空");
        }
        if (StringUtils.isEmpty(sysArticle.getLabels())) {
            return AjaxResult.error("标签不可为空");
        }
        //填充数据
        sysArticle.setViewCount(0L);
        sysArticle.setState(WebConstants.article.ARTICLE_PUBLISH_STATE);
        sysArticle.setCreateTime(DateUtils.getNowDate());
        sysArticle.setUpdateTime(DateUtils.getNowDate());
        int result = sysArticleMapper.insertSysArticle(sysArticle);
        solrService.addArticle(sysArticle);
        //打散标签存放数据库
        this.breakUpLabels(sysArticle.getLabels());
        return AjaxResult.success(result);
    }

    /**
     * 修改文章
     *
     * @param sysArticle 文章
     * @return 结果
     */
    @Override
    public int updateSysArticle(SysArticle sysArticle) {
        sysArticle.setUpdateTime(DateUtils.getNowDate());
        int result = sysArticleMapper.updateSysArticle(sysArticle);
        //打散标签存储在数据中
        this.breakUpLabels(sysArticle.getLabels());
        //判断是否为草稿
        if (WebConstants.article.ARTICLE_DRAFT_STATE.equals(sysArticle.getState())) {
            return result;
        }
        //删除缓存中的数据
        redisCache.deleteObject(CacheConstants.SYS_ARTICLE_KEY + sysArticle.getId());
        //更新搜索库中的数据
        solrService.updateArticle(sysArticle);
        return result;
    }

    /**
     * 保存草稿
     *
     * @param sysArticle
     * @return
     */
    @Override
    public int insertDraftArticle(SysArticle sysArticle) {
        sysArticle.setCreateTime(DateUtils.getNowDate());
        sysArticle.setUpdateTime(DateUtils.getNowDate());
        sysArticle.setState(WebConstants.article.ARTICLE_DRAFT_STATE);
        this.breakUpLabels(sysArticle.getLabels());
        return sysArticleMapper.insertSysArticle(sysArticle);
    }

    /**
     * 批量删除文章
     *
     * @param ids 需要删除的文章主键
     * @return 结果
     */
    @Override
    public int deleteSysArticleByIds(Long[] ids) {
        //return sysArticleMapper.deleteBatchIds(Arrays.asList(ids));
        return sysArticleMapper.deleteSysArticleByIds(ids);
    }

    /**
     * 删除文章信息
     *
     * @param id 文章主键
     * @return 结果
     */
    @Override
    public int deleteSysArticleById(Long id) {
        int result = sysArticleMapper.deleteById(id);
        redisCache.deleteObject(CacheConstants.SYS_ARTICLE_KEY + id);
        solrService.deleteArticle(id);
        //TODO 删除对应评论
        return result;
    }

    /**
     * 打散标签添加标签数字
     *
     * @param labels
     */
    private void breakUpLabels(String labels) {
        String[] labelsArr = labels.split(",");
        for (String s : labelsArr) {
            labelsMapper.updateCountByName(s);
        }
    }
}
